home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 317_01 / gnencode.c < prev    next >
C/C++ Source or Header  |  1990-06-16  |  6KB  |  191 lines

  1. /*    $Id: gnencode.c 1.2 90/06/09 18:24:51 marking Exp $
  2.  *
  3.  NAME
  4.  *    gnencode.c -- routines for bit and byte encoding
  5.  *
  6.  TYPE
  7.  *    C procedures
  8.  *
  9.  SYNOPSIS
  10.  *    void initialize_encode ();
  11.  *    void encode_word (unsigned short codeword, short length);
  12.  *
  13.  DESCRIPTION
  14.  *    Support routines used in encoding group 3 and group 4 images.
  15.  *
  16.  RETURNS
  17.  *
  18.  LEGAL
  19.  *    Copyright 1989, 1990 Michael P. Marking, Post Office Box 8039,
  20.  *    Scottsdale, Arizona 85252-8039. All rights reserved.
  21.  *
  22.  *    License is granted by the copyright holder to distribute and use this
  23.  *    code without payment of royalties or the necessity of notification as
  24.  *    long as this notice (all the text under "LEGAL") is included.
  25.  *
  26.  *    Reference: $Id: gnencode.c 1.2 90/06/09 18:24:51 marking Exp $
  27.  *
  28.  *    This program is offered without any warranty of any kind. It includes
  29.  *    no warranty of merchantability or fitness for any purpose. Testing and
  30.  *    suitability for any use are the sole responsibility of the user.
  31.  * 
  32.  HISTORY
  33.  *    $Log:    gnencode.c $
  34.  * Revision 1.2  90/06/09  18:24:51  marking
  35.  * clean up comments for release
  36.  * 
  37.  * Revision 1.1  89/06/30  17:00:00  marking
  38.  * Initial revision
  39.  * 
  40.  *
  41.  NOTES
  42.  *    1.    There are two versions of encode_word (). Refer to the remark
  43.  *        below and comment-out one or the other.
  44.  *
  45.  PORTABILITY
  46.  *    Tested using Microsoft C 5.1. Some memory models may not work due to
  47.  *    the large encoding arrays.
  48.  *
  49.  *    There is a non-portable use of "global" variables in the file g3g4.h,
  50.  *    about which a minority of compilers will justifiably complain. Certain
  51.  *    variables are declared in g3g4.h without extern keywords. Strictly
  52.  *    speaking, they should be declared extern in all but one module, but
  53.  *    that would require complication of g3g4.h. If it gets past your
  54.  *    compiler and linker, you can probably ignore it.
  55.  *
  56.  SEE ALSO
  57.  *    g3sencod.c, g4sencod.c
  58.  *
  59.  INFORMATION
  60.  *    Although there is no support offered with this program, the author will
  61.  *    endeavor to correct errors. Updates will also be made available from
  62.  *    time to time.
  63.  *
  64.  *    Contact: Michael P. Marking, Post Office Box 8039, Scottsdale, Arizona
  65.  *    85252-8039 USA. Replies are not guaranteed to be swift. Beginning
  66.  *    July 1990, e-mail may be sent to uunet!ipel!marking.
  67.  *
  68.  *    Also beginning in July 1990, this code will be archived at the
  69.  *    ipel!phoenix BBS in file g3g4.zoo. The 24-hour telephone number
  70.  *    for 300/1200/2400 is (602)274-0462. When logging in, specify user
  71.  *    "public", system "bbs", and password "public".
  72.  *
  73.  *    This code is also available from the C Users Group in volume 317.
  74.  */
  75.  
  76. #include "g3g4.h"
  77.  
  78. /*
  79.  *    initialize the bit-encoding routines
  80.  */
  81.  
  82. void initialize_encode ()
  83. {
  84.   static unsigned char msb_mask [8] =
  85.     { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
  86.   static unsigned char lsb_mask [8] =
  87.     { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
  88.   static unsigned char msb_head_mask [8] =
  89.     { 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF };
  90.   static unsigned char lsb_head_mask [8] =
  91.     { 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
  92.   static unsigned char msb_tail_mask [8] =
  93.     { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 };
  94.   static unsigned char lsb_tail_mask [8] =
  95.     { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 };
  96.   output_fill_order = MSB_FIRST;    /* some implementations might
  97.                         want to change this */
  98.   encode_buffer = 0;
  99.   encode_position = 0;
  100.   if (output_fill_order == MSB_FIRST)
  101.   {
  102.     encode_mask = msb_mask;
  103.     encode_head_mask = msb_head_mask;
  104.     encode_tail_mask = msb_tail_mask;
  105.   }
  106.   else /* output_fill_order == LSB_FIRST */
  107.   {
  108.     encode_mask = lsb_mask;
  109.     encode_head_mask = lsb_head_mask;
  110.     encode_tail_mask = lsb_tail_mask;
  111.   }
  112.   pending_black = 0;
  113.   pending_white = 0;
  114. }
  115.  
  116. /*
  117.  *    append a codeword of the specified length in bits to the end
  118.  *    of the current output file
  119.  */
  120.  
  121. void encode_word (unsigned short codeword, short length)
  122. {
  123. /*********
  124.     There are two versions of this procedure.  One or the other
  125.     is to be commented out.  The first is somewhat faster,
  126.     especially on a 386 because it makes use of the barrel
  127.     shifter.  Its limitation is the assumption that the output
  128.     file is filled most-significant-bit first.  The second is
  129.     a little slower, but doesn't make the assumption.
  130. ********/
  131.  
  132. /* the faster routine, with the assumption . . . */
  133.   short first_count, second_count, remaining, new_encode_position;
  134.   static char limit_8 [] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8,
  135.     8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8};
  136.   if (length)
  137.   {
  138.     new_encode_position = limit_8 [encode_position + length];
  139.     first_count = new_encode_position - encode_position;
  140.     encode_buffer |= (codeword >> (encode_position + 8));
  141.     encode_position = new_encode_position;
  142.     remaining = length - first_count;
  143.     if (encode_position > 7)
  144.     {
  145.       (*p_encode_next_byte) (encode_buffer);
  146.       if (remaining)
  147.       {
  148.     encode_position = limit_8 [remaining];
  149.     second_count = encode_position;
  150.     remaining -= second_count;
  151.     encode_buffer = ((unsigned char) (codeword >> (8 - first_count)))
  152.         & encode_head_mask [second_count - 1];
  153.     if (encode_position > 7)
  154.     {
  155.       (*p_encode_next_byte) (encode_buffer);
  156.       if (remaining)
  157.       {
  158.         encode_buffer
  159.           = ((unsigned char) (codeword << first_count))
  160.         & encode_head_mask [remaining - 1];
  161.         encode_position = remaining;
  162.       }
  163.       else { encode_buffer = 0; encode_position = 0; }
  164.     }
  165.       }
  166.       else { encode_buffer = 0; encode_position = 0; }
  167.     }
  168.   }
  169.  
  170. /* the slower routine, with no assumption about output file bit order . . . */
  171. /*
  172.   static short read_mask [16] = {0x8000, 0x4000, 0x2000, 0x1000, 0x0800,
  173.     0x0400, 0x0200, 0x0100, 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004,
  174.     0x0002, 0x0001};
  175.   short j1;
  176.   for (j1 = 0; j1 < length; j1 ++)
  177.   {
  178.     if (read_mask [j1] & codeword)
  179.       encode_buffer |= encode_mask [encode_position];
  180.     encode_position++;
  181.     if (encode_position > 7)
  182.     {
  183.       (*p_encode_next_byte) (encode_buffer);
  184.       encode_position = 0;
  185.       encode_buffer = 0;
  186.     }
  187.   }
  188. */
  189. }
  190. /*    end $RCSfile: gnencode.c $ */
  191.